﻿using System.Drawing;
using Platformer_Example.Controller.Interfaces;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Platformer_Example.Controller.Map
{
    public static class MapAnalyser
    {
        public static MapCellData[,] ExtractData(string mapPath)
        {
            MapCellData[,] data;
            using (Bitmap map = new Bitmap(mapPath))
            {
                data = new MapCellData[map.Width, map.Height];

                for (int x = 0; x < map.Width; x++)
                {
                    for (int y = 0; y < map.Height; y++)
                    {
                        var pixel = map.GetPixel(x, y);

                        byte r = pixel.R;
                        byte g = pixel.G;
                        byte b = pixel.B;

                        var value = (r << 16) + (g << 8) + b;

                        var mapData = new MapCellData(value);
                        data[x, y] = mapData;
                    }
                }
            }
            return data;
        }

        static int GetTerrainValue(this MapCellData[,] data, int x, int y)
        {
            if (x < 0 || x >= data.GetLength(0) || y < 0 || y >= data.GetLength(1))
                return 1;
            return data[x, y].IsTerrain ? 1 : 0;
        }

        static int GetSurroundingValue(this MapCellData[,] data, int x, int y)
        {

            return data.GetTerrainValue(x + 1, y) * 1 +
                   data.GetTerrainValue(x, y - 1) * 2 +
                   data.GetTerrainValue(x - 1, y) * 4 +
                   data.GetTerrainValue(x, y + 1) * 8 +
                   data.GetTerrainValue(x + 1, y - 1) * 16 +
                   data.GetTerrainValue(x - 1, y - 1) * 32 +
                   data.GetTerrainValue(x - 1, y + 1) * 64 +
                   data.GetTerrainValue(x + 1, y + 1) * 128;
        }

        public static TE_Vector2 GetLadderSize(this MapCellData[,] data, int x, int y)
        {
            var y2 = y + 1;
            while (y2 < data.GetLength(1) && data[x, y2].IsLadder)
            {
                y2++;
            }

            return new TE_Vector2(1, y2 - y);
        }

        public static TE_Vector2 GetTerrainSize(this MapCellData[,] data, int x, int y)
        {
            var x2 = x + 1;
            while (x2 < data.GetLength(0))
            {
                if (!data[x, y].IsSameTerrainType(data[x2, y]))
                    break;

                data[x2, y].IsChecked = true;

                x2++;
            }

            var y2 = y + 1;
            bool isValidRow = true;
            while (isValidRow && y2 < data.GetLength(1))
            {
                for (int x3 = x; x3 < x2; x3++)
                {
                    if (!data[x, y].IsSameTerrainType(data[x3, y2]))
                    {
                        isValidRow = false;
                        break;
                    }
                }

                if (isValidRow)
                {
                    for (int x3 = x; x3 < x2; x3++)
                    {
                        data[x3, y2].IsChecked = true;
                    }

                    y2++;
                }
            }

            return new TE_Vector2(x2 - x, y2 - y);
        }

        public static void AnalyseData(MapCellData[,] data, IMap map)
        {
            for (int x = 0; x < data.GetLength(0); x++)
            {
                for (int y = 0; y < data.GetLength(1); y++)
                {
                    data[x, y].Type = data.GetSurroundingValue(x, y);
                }
            }

            for (int x = 0; x < data.GetLength(0); x++)
            {
                for (int y = 0; y < data.GetLength(1); y++)
                {
                    if (data[x, y].IsStair)
                    {
                        map.AddStair(data[x, y].Terrain, data[x, y].Stair, new TE_Vector2(x, y));
                    }
                    else if (data[x, y].IsLadder)
                    {
                        var size = data.GetLadderSize(x, y);
                        map.AddLadder(data[x, y].Terrain, size, new TE_Vector2(x, y));

                        for (int y2 = y; y2 < y + size.Y; y2++)
                        {
                            if (data[x, y2].IsTerrain)
                            {
                                var terrainSize = data.GetTerrainSize(x, y2);
                                map.AddForegroundTerrain(data[x, y2].Terrain, data[x, y2].Type, terrainSize, new TE_Vector2(x, y2));
                            }
                                
                        }
                    }
                    else if (data[x, y].IsTerrain)
                    {
                        var size = data.GetTerrainSize(x, y);
                        map.AddTerrain(data[x, y].Terrain, data[x, y].Type, size, new TE_Vector2(x, y));
                    }

                }
            }
        }
    }
}